﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using Tulde.Core;

using System.Windows.Threading;
using System.Text;
using Tulde.MP3tunes.Model;
using Tulde.MP3tunes;

namespace MP3tunes.LockerPlayer.Pages
{
    public partial class MediaPlayer : PhoneApplicationPage
    {
        public App CurrentApplication
        {
            get
            {
                return App.Current as App;
            }
        }
        private double currentVolume;
        private bool isMuted = false;
        private bool isPaused = false;
        DispatcherTimer timer;
    
        public event EventHandler<MediaPlayerEventArgs> TrackChanged;
        public event EventHandler<MediaPlayerEventArgs> TrackPlaying;


        public bool IsFirstPlay
        {
            get;
            set;
        }
        protected Track SelectedTrack
        {
            get
            {
                return this.listTracks.SelectedItem as Track;
            }
        }
        private int _currentTrackIndex;
        public int CurrentTrackIndex
        {
            get
            {
                return this._currentTrackIndex;
            }
            private set
            {
                this._currentTrackIndex = value;
                this.SetCurrentTrack(this.CurrentTrack);


            }
        }
        public Track CurrentTrack
        {
            get
            {
                if (this.CurrentTrackIndex < this.TrackCollection.Count && this.CurrentTrackIndex > 0)
                {
                    return this.TrackCollection[this.CurrentTrackIndex];
                }
                else
                {
                    //don't want to fire the set event
                    this._currentTrackIndex = 0;
                    if (this._currentTrackIndex < this.TrackCollection.Count)
                        return this.TrackCollection[this.CurrentTrackIndex];
                    else
                        return null;
                }
            }
        }
        private List<Track> _trackCollection;
        public List<Track> TrackCollection
        {
            get
            {
                if (_trackCollection == null)
                {
                    _trackCollection = new List<Track>();
                }
                return _trackCollection;
            }
            set
            {
                this._trackCollection = value;
                if (this._trackCollection.Any())
                {

                    this.listTracks.DataContext = this._trackCollection;
                   this.listTracks.SelectionChanged -= new SelectionChangedEventHandler(listTracks_SelectionChanged);
                    this._currentTrackIndex = 0;
                    this.listTracks.SelectionChanged += new SelectionChangedEventHandler(listTracks_SelectionChanged);

                }
            }
        }
        private void SetCurrentTrack(Track track)
        {
            this.listTracks.SelectedItem = track;
            this.SetDisplayBackground(track);
        }

        protected void OnTrackChanged(Track track)
        {
            if (this.TrackChanged != null)
            {
                this.TrackChanged(this, new MediaPlayerEventArgs { Track = track });
            }
        }
        protected void OnTrackPlay(Track track)
        {
            if (this.TrackPlaying != null)
            {
                this.TrackPlaying(this, new MediaPlayerEventArgs { Track = track });
            }
        }
        public void PlayTrack(Track track)
        {
            for (int i = 0; i < this.TrackCollection.Count; i++)
            {
                if (this.TrackCollection[i].TrackId == track.TrackId)
                {
                    this.CurrentTrackIndex = i;
                    this.Play();
                    break;
                }
            }
        }
        private Album SelectedAlbum { get; set; }
        private Playlist SelectedPlaylist { get; set; }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {

            
            base.OnNavigatedTo(e);
            if (this.player.CurrentState == MediaElementState.Playing)
            {
                this.timer.Start();
            }
            else
            {
                this.IsFirstPlay = true;
                this.SelectedAlbum = NavigationContext.GetViewModelFromQueryParameters<Album>();
                this.SelectedPlaylist = NavigationContext.GetViewModelFromQueryParameters<Playlist>();
                if (this.SelectedAlbum == null)
                {
                    //assume we are shuffling tracks
                    // this.PlayPlaylist();
                }
                else
                {
                    // this.panorma1.Title = this.SelectedArtist.ArtistName;
                    this.artistLabel.Text = this.SelectedAlbum.ArtistName;
                    this.nowPlaying.Text = this.SelectedAlbum.AlbumTitle;


                }
            }

        }
        protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            try
            {
               this.timer.Stop();
               //this.player.Stop();
            }
            catch { }
        }

        public MediaPlayer()
        {
            InitializeComponent();
            this.Loaded+=new RoutedEventHandler(MediaPlayer_Loaded);
            this.CurrentApplication.RootFrame.Obscured += new EventHandler<ObscuredEventArgs>(RootFrame_Obscured);
            this.CurrentApplication.RootFrame.Unobscured += new EventHandler(RootFrame_Unobscured);
        

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(200);
            timer.Tick += new EventHandler(timer_Tick);

            this.player.MediaEnded += new RoutedEventHandler(player_MediaEnded);
            this.player.MediaFailed += new EventHandler<ExceptionRoutedEventArgs>(player_MediaFailed);
            this.player.MediaOpened += new RoutedEventHandler(player_MediaOpened);
            this.player.BufferingProgressChanged += new RoutedEventHandler(player_BufferingProgressChanged);
            this.player.CurrentStateChanged += new RoutedEventHandler(player_CurrentStateChanged);
            this.player.DownloadProgressChanged += new RoutedEventHandler(player_DownloadProgressChanged);
            player.Volume = 1;
            this.mute.Click += new RoutedEventHandler(mute_Click);
            this.listTracks.SelectionChanged += new SelectionChangedEventHandler(listTracks_SelectionChanged);

           this.SetButtonState(false);
        }

        void RootFrame_Unobscured(object sender, EventArgs e)
        {
            this.RestoreItems();
        }

        void RootFrame_Obscured(object sender, ObscuredEventArgs e)
        {
            this.SuspendItems();
        }
        /// <summary>
        /// suspends all non critical items when the app reaches an obscured state.  This occurs when the screen is locked.
        /// Stop all timers, storyboards etc.
        /// </summary>
        private void SuspendItems()
        {
            this.timer.Stop();
            this.progress1.IsIndeterminate = false;
        }
        private void RestoreItems()
        {
            this.timer.Start();

      
            
        }


        void MediaPlayer_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.SelectedAlbum != null)
            {
                Tulde.MP3tunes.Mp3TunesMusicService.GetAlbumTracks(this.SelectedAlbum, tracks =>
                {
                    this.TrackCollection = tracks.Tracks;
                    this.PlayFirstSong();
                });
            }
            else if (this.SelectedPlaylist != null)
            {
                Tulde.MP3tunes.Mp3TunesMusicService.GetPlaylist(this.SelectedPlaylist, tracks =>
                {

                    var list = new List<Track>();
                    if (!tracks.Tracks.Empty())
                    {
                        list.AddRange(tracks.Tracks);
                        if (list.Any())
                        {
                            this.TrackCollection = list;
                            this.PlayFirstSong();
                        }
                        else
                        {
                            this.status.Text = "Found no songs.";
                            this.progress1.IsIndeterminate = false;
                            this.SetButtonState(false);
                        }
                    }
                    else
                    {
                        this.status.Text = "Found no songs.";
                        this.progress1.IsIndeterminate = false;
                        this.SetButtonState(false);
                    }

                });
            }
            this.volume.Value = this.player.Volume;
        }
        private void PlayFirstSong()
        {
            this.listTracks.SelectionChanged -= new SelectionChangedEventHandler(listTracks_SelectionChanged);
            this.SetCurrentTrack(this.CurrentTrack);
            this.PlayTrack(this.CurrentTrack);
            this.listTracks.SelectionChanged += new SelectionChangedEventHandler(listTracks_SelectionChanged);
        }

        private void SetDisplayBackground(Track track)
        {
     
            ImageBrush backgroundBrush = null;


            backgroundBrush = new ImageBrush();
            backgroundBrush.ImageSource = AlbumArtResource.Load(new Album { AlbumId = track.AlbumId });

            backgroundBrush.Opacity = 0.30;
            backgroundBrush.Stretch = Stretch.Fill;

            this.mediaPane.Background = backgroundBrush;

            this.albumArt.Source = AlbumArtResource.Load(new Album { AlbumId = track.AlbumId });


        }

        private void PlayPlaylist()
        {
        }

        private void playlistList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
        void listTracks_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.SelectedTrack == null)
            {
                return;
            }
            this.isPaused = false;
            this.PlayTrack(this.SelectedTrack);
        }
        #region Actions
        void timer_Tick(object sender, EventArgs e)
        {
            //if (!isDragging)
            //{
            //    seekBar.Value = this.player.Position.TotalSeconds;
            //}
            this.Dispatcher.BeginInvoke(new Action(() =>
            {

                var p = this.player.Position;
                this.seekBar.Value = this.player.Position.TotalSeconds;
                this.elapsedTxt.Text = this.FormatTime(p);// String.Format("{0}:{1}", p.Minutes, p.Seconds);
            }));

        }
        private void SetButtonState(bool enabled)
        {

            this.play.Visibility = enabled ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
            this.next.Visibility = this.play.Visibility;
            this.previous.Visibility = this.play.Visibility;
           // this.pause.Visibility  = !enabled;
            // this.stop.Visibility = this.play.Visibility;
        }
        public void Play()
        {
            if (!Microsoft.Xna.Framework.Media.MediaPlayer.GameHasControl)
            {
                MessageBoxResult result = MessageBox.Show("Media is currently playing in the background.  Continuing will stop all background media.  Continue?", "User Action Required", MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.Cancel)
                {
                    return;
                }
                
            }
            if (this.CurrentTrack != null)
            {


                this.nowPlaying.Text = this.CurrentTrack.AlbumTitle;
                this.artistLabel.Text = this.CurrentTrack.ArtistName;
                if (!this.isPaused)
                {

                    LockerPlayerService s = new LockerPlayerService();
                    Uri uri = s.CreateServiceEndpoint(LockerStorageOperations.lockerPlay, new PlayerServiceParameters
                    {
                        FileFormat = "mp3",
                        Bitrate = Bitrate.b96000,
                        FileKey = this.SelectedTrack.TrackFileKey,
                        FileName = this.CurrentTrack.TrackTitle + ".mp3"

                    });
                    this.SetButtonState(true);
                    this.OnTrackChanged(this.CurrentTrack);
                    this.player.Stop();
                    this.play.Visibility = System.Windows.Visibility.Collapsed;
                    this.pause.Visibility = System.Windows.Visibility.Visible;
                    this.SetProgressBar(true);

                    this.status.Text = "Loading " + this.CurrentTrack.TrackTitle;


                    this.player.Source = uri;
                    // this.player.Play();
                }
                else
                {
                    this.isPaused = false;
                    this.timer.Start();
                    this.play.Visibility = System.Windows.Visibility.Collapsed;
                    this.pause.Visibility = System.Windows.Visibility.Visible;
                    this.status.Text = "Playing " + this.CurrentTrack.TrackTitle;
                    this.player.Play();
                }
            }
            else
            {
                this.status.Text = "Stopped.  No tracks found.";
            }
        }


        public void Stop()
        {
            this.timer.Stop();
            this.SetProgressBar(false);
            this.play.Visibility = System.Windows.Visibility.Visible;
            this.pause.Visibility = System.Windows.Visibility.Collapsed;
            this.player.Stop();
        }
        public void Pause()
        {
            this.SetProgressBar(false);
            this.timer.Stop();
            this.status.Text = "Paused " +  this.CurrentTrack.TrackTitle;
            this.play.Visibility = System.Windows.Visibility.Visible;
            this.pause.Visibility = System.Windows.Visibility.Collapsed;
            this.isPaused = true;
            this.player.Pause();
        }
        public void Next()
        {
            this.CurrentTrackIndex++;
            if (this.CurrentTrackIndex >= this.TrackCollection.Count)
                this.CurrentTrackIndex = 0;
            this.timer.Stop();
            this.Play();
        }
        public void Previous()
        {
            
                this.CurrentTrackIndex--;
                if (this.CurrentTrackIndex <= 0)
                    this.CurrentTrackIndex = 0;
                this.timer.Stop();
                this.Play();
            
        }
        public void Mute()
        {
            if (this.isMuted)
            {
                // this.volume.Value = this.currentVolume;
                this.player.Volume = this.currentVolume;
                this.isMuted = false;
            }
            else
            {

                this.currentVolume = this.player.Volume;
                this.isMuted = true;
                //this.volume.Value = 0;
                this.player.Volume = 0;
            }
        }

        
        void player_BufferingStarted(object sender, RoutedEventArgs e)
        {
            //set the selected item;
            this.listTracks.SelectionChanged -= new SelectionChangedEventHandler(listTracks_SelectionChanged);
            this.SetCurrentTrack(this.SelectedTrack);
            this.listTracks.SelectionChanged += new SelectionChangedEventHandler(listTracks_SelectionChanged);
        }


        void mute_MouseUp(object sender, MouseButtonEventArgs e)
        {

            this.Mute();
        }


        void player_BufferingProgressChanged(object sender, RoutedEventArgs e)
        {

        }
        void player_MediaOpened(object sender, RoutedEventArgs e)
        {
            this.buttonPanel.Visibility = System.Windows.Visibility.Visible;

            if (this.player.NaturalDuration.HasTimeSpan)
            {
                TimeSpan ts = this.player.NaturalDuration.TimeSpan;
                seekBar.Maximum = ts.TotalSeconds;
                seekBar.SmallChange = 1;
                seekBar.LargeChange = Math.Min(10, ts.Seconds / 10);

                //     this.status.Text = "Playing " + this.CurrentTrack.ArtistName + " - " + this.CurrentTrack.TrackTitle;
                //     this.OnTrackPlay(this.CurrentTrack);
            }
            if (!this.IsFirstPlay)
            {


                // timer.Start();

                this.status.Text = "Playing " +  this.CurrentTrack.TrackTitle;

            }
            else
            {
                this.IsFirstPlay = false;
                this.player.Pause();
                this.player.Play();
                this.status.Text = "Playing " + this.CurrentTrack.TrackTitle;
                this.OnTrackPlay(this.CurrentTrack);
            }
           

            if (this.player.NaturalDuration.HasTimeSpan)
            {
                // this.durationTxt.Text = string.Format("{0:mm\\:ss}", player.NaturalDuration.TimeSpan);
                this.durationTxt.Text = this.FormatTime(player.NaturalDuration.TimeSpan); // String.Format("{0}:{1}", player.NaturalDuration.TimeSpan.Minutes, player.NaturalDuration.TimeSpan.Seconds);
                timer.Start();
            }
        }

        void mute_Click(object sender, RoutedEventArgs e)
        {
            this.Mute();
        }
        void player_DownloadProgressChanged(object sender, RoutedEventArgs e)
        {

        }

        void player_CurrentStateChanged(object sender, RoutedEventArgs e)
        {

        }
        void player_MediaEnded(object sender, RoutedEventArgs e)
        {
            this.Next();
        }

        void player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            this.status.Text = e.ErrorException.Message;
        }
        public void SetProgressBar(bool state)
        {
            this.progress1.IsIndeterminate = state;
            this.progress1.IsEnabled = state;
        }
        #endregion

        private string FormatTime(TimeSpan ts)
        {
            int hour = ts.Hours;
            int minute = ts.Minutes;
            int seconds = ts.Seconds;

            StringBuilder b = new StringBuilder();
            b.Append(hour < 10 ? "0" + hour : hour.ToString());
            b.Append(":");
            b.Append(minute < 10 ? "0" + minute : minute.ToString());
            b.Append(":");
            b.Append(seconds < 10 ? "0" + seconds : seconds.ToString());
            return b.ToString();
        }

        private void previous_Click(object sender, RoutedEventArgs e)
        {
            this.Previous();
        }

        private void play_Click(object sender, RoutedEventArgs e)
        {
            this.Play();
        }

        private void pause_Click(object sender, RoutedEventArgs e)
        {
            this.Pause();
        }

        private void next_Click(object sender, RoutedEventArgs e)
        {
            this.Next();
        }

        private void volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            this.player.Volume = e.NewValue;
        }

        private void volume_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            this.player.Volume = this.volume.Value;
        }
    }
    public class MediaPlayerEventArgs : EventArgs
    {
        public Track Track { get; set; }
    }
}